﻿using Fleck;
using FyAutoStartService.Models;
using FySystem.Extension;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Threading.Tasks;

namespace FyAutoStartService
{
    /// <summary>
    /// 文件相关的接口
    /// </summary>
    internal class WSocketFileApi
    {
        /// <summary>
        /// 列出目录
        /// </summary>
        /// <param name="message"></param>
        /// <param name="connection"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        internal static DirResult ListDir(WSMessageInfo message, IWebSocketConnection connection)
        {
            DirResult res = new DirResult();
            res.Files = new List<FileAndDirectory>();
            try
            {
                if (message == null)
                    throw new Exception("传入参数为空~");

                bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);

                res.Path = string.IsNullOrWhiteSpace(message.val) ? "/" : message.val;

                //对相对路径进行处理
                if (isWindows)
                {
                    if (string.IsNullOrWhiteSpace(Global.RootPath))
                        res.Path = res.Path.TrimStart('/');
                }
                if (res.Path.EndsWith('/') == false)
                    res.Path += '/';

                //服务器的绝对路径
                string absolutePath = GetAbsolutePath(message.val);

                if (string.IsNullOrWhiteSpace(absolutePath) && isWindows)
                {
                    //列出驱动器
                    DriveInfo[] drives = DriveInfo.GetDrives();
                    if (drives.IsNullOrEmpty() == false)
                    {
                        foreach (var item in drives)
                        {
                            //if (item.IsReady)
                            res.Files.Add(new FileAndDirectory(true, item.Name.Trim('\\')));
                        }
                    }
                }
                else
                {
                    //列出子目录
                    absolutePath = absolutePath + '/';
                    DirectoryInfo di = new DirectoryInfo(absolutePath);
                    if (di.Exists)
                    {
                        var subPathes = di.GetDirectories();
                        var subFiles = di.GetFiles();

                        if (subPathes.IsNullOrEmpty() == false)
                        {
                            foreach(var item in subPathes)
                            {
                                if(item.Attributes!= FileAttributes.Hidden)
                                {
                                    res.Files.Add(new FileAndDirectory(true, item.Name));
                                }
                            }
                        }

                        if (subFiles.IsNullOrEmpty() == false)
                        {
                            foreach(var item in subFiles)
                            {
                                if(item.Attributes!= FileAttributes.Hidden)
                                {
                                    res.Files.Add(new FileAndDirectory(false, item.Name, item.Length));
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception)
            {
                throw;
            }
            return res;
        }

        private static void CheckParam(WSMessageInfo message)
        {
            try
            {
                if (message == null)
                    throw new Exception("传入参数为空~");
                if (string.IsNullOrWhiteSpace(message.val))
                    throw new Exception("传入参数为空~");
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 获取绝对路径，返回的结果最后不包含分隔符
        /// </summary>
        /// <param name="relativePath"></param>
        /// <returns></returns>
        internal static string GetAbsolutePath(string relativePath)
        {
            string res = string.Empty;
            try
            {
                relativePath = relativePath.Trim('\\').Trim('/');
                if (string.IsNullOrWhiteSpace(Global.RootPath))
                    res = relativePath;
                else
                    res = $"{Global.RootPath}/{relativePath}";

                res = res.Trim('/');
            }
            catch (Exception)
            {
                throw;
            }
            return res;
        }

        /// <summary>
        /// 获取需要下载的文件列表
        /// </summary>
        /// <param name="info"></param>
        /// <param name="connection"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        internal static object GetDownloadFiles(WSMessageInfo info, IWebSocketConnection connection)
        {
            try
            {
                CheckParam(info);

                List<TransferFile> dfiles = new List<TransferFile>();

                FileDownloadRequest request = JsonSerializer.Deserialize<FileDownloadRequest>(info.val);

                List<KeyValue> requestAbsoluteFiles = new List<KeyValue>();
                string requestPath = request.Path.TrimEnd('\\').TrimEnd('/');

                foreach (var item in request.FileNames)
                {
                    //遍历传入的相对路径，组装出服务器端的文件或目录的绝对路径
                    string absoluteName = $"{GetAbsolutePath(request.Path)}/{item}";
                    requestAbsoluteFiles.Add(new KeyValue($"{requestPath}/{item}", absoluteName));
                }

                foreach(var item in requestAbsoluteFiles)
                {
                    if (File.Exists(item.Val))
                    {
                        //如果是文件
                        dfiles.Add(new TransferFile(item.Key, item.Val, new FileInfo(item.Val).Length));
                    }
                    else if (Directory.Exists(item.Val))
                    {
                        //如果是文件夹
                        DirectoryInfo di = new DirectoryInfo(item.Val);

                        //递归获取子文件
                        List<TransferFile> subFiles = FileTransfer.RecursionFiles(di, Global.RootPath);
                        if (subFiles.IsNullOrEmpty() == false)
                            dfiles.AddRange(subFiles);
                    }
                    else
                    {
                        TransferFile file = new TransferFile();
                        file.IsExists = false;
                        file.FileName = item.Key;
                        dfiles.Add(file);
                    }
                }

                if (dfiles.Count <= 0)
                    throw new Exception("选中的文件夹内没有文件~");

                //添加文件传输任务
                string transferToken = Guid.NewGuid().ToString();
                TransferTask task = new TransferTask(transferToken, dfiles);
                Global.FileTransfer.AddTransferTask(task);

                return new
                {
                    TransferToken = transferToken,
                    Path = request.Path,
                    Files = dfiles
                };
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 客户端请求上传文件
        /// </summary>
        /// <param name="info"></param>
        /// <param name="connection"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        internal static object CreateUploadTask(WSMessageInfo info, IWebSocketConnection connection)
        {
            try
            {
                CheckParam(info);

                JsonDocument doc = JsonDocument.Parse(info.val);
                JsonElement ele = doc.RootElement;
                JsonObject obj = JsonObject.Create(ele);

                string basePath = obj["Path"].ToString();
                string absolutePath = GetAbsolutePath(basePath);
                JsonArray files = obj["Files"].AsArray();

                if (files == null)
                    throw new Exception("上传文件夹内没有文件~");
                if (files.Count <= 0)
                    throw new Exception("上传文件夹内没有文件~");

                List<TransferFile> dfiles = new List<TransferFile>();

                foreach (var item in files)
                {
                    string relativeName = item["File"].ToString();
                    string fileGuid = item["FileGUID"].ToString();
                    string absoluteName = $"{absolutePath}/{relativeName}";

                    TransferFile file = new TransferFile(fileGuid, absoluteName);
                    dfiles.Add(file);
                }

                string transferToken = Guid.NewGuid().ToString("N");
                TransferTask task = new TransferTask(transferToken, dfiles);
                Global.FileTransfer.AddTransferTask(task);

                return new
                {
                    TransferToken = transferToken
                };
            }
            catch (Exception)
            {
                throw;
            }
        }
    }
}
